package com.qd.hik.service;

import cn.hutool.http.HttpResponse;
import com.cdqidi.exception.ApiException;
import com.cdqidi.httpclientbootstart.util.HttpUtil;
import com.cdqidi.util.JacksonUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.qd.hik.base.HkBaseTokenDTO;
import com.qd.hik.dto.HkBaseHttpResp;
import com.qd.hik.dto.parkinfo.*;
import com.qd.hik.token.HkAccessToken;
import com.qd.hik.token.HkAccessTokenManager;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 2.3  车场
 *
 * @author sjk
 * @create 2024-05-29 14:53
 * @since 1.0.0
 */
@Service
@Slf4j
@RequiredArgsConstructor
@HkAccessToken
public class HkParkInfoService {
    private final ObjectMapper objectMapper;
    private final HkBaseTokenDTO hkBaseTokenDTO;
    private final HttpUtil httpUtil;
    /**
     * 2.3.1 分页获取停车场信息
     */
    private static final String DEALER_PARK_INFO_URL = "/artemis/api/v1/dealer/parkinfos";
    /**
     * 2.3.2 获取单个停车场信息
     */
    private static final String DEALER_PARK_CODE_URL = "/artemis/api/v1/dealer/parkinfo/{0}";
    /**
     * 2.3.3 获取剩余车位数
     */
    private static final String DEALER_PARK_REMAINING_SPACE_URL = "/artemis/api/v1/dealer/parkRemainingSpace/{0}";
    /**
     * 2.3.4 获取出入口
     */
    private static final String DEALER_GATE_INFOS_URL = "/artemis/api/v1/dealer/gateInfos";
    /**
     * 2.3.5 获取车道
     */
    private static final String DEALER_LANE_INFOS_URL = "/artemis/api/v1/dealer/laneInfos";
    /**
     * 2.3.6 获取泊位
     */
    private static final String DEALER_BERTH_INFOS_URL = "/artemis/api/v1/dealer/berthInfos";

    /**
     * 2.3.1 分页获取停车场信息
     *
     * @param hkParkReq 请求参数
     *                  {
     *                  "pageNo":1,
     *                  "pageSize": 10,
     *                  "parkName":""
     *                  }
     */
    @SneakyThrows
    public HkBaseHttpResp<HkParkParentResp> parks(HkParkReq hkParkReq) {
        String json = JacksonUtil.getObjectMapper().writeValueAsString(hkParkReq);
        String post = httpUtil.sendHttpsPost(hkBaseTokenDTO.getBaseUrl() + DEALER_PARK_INFO_URL, json, Map.of("access_token", HkAccessTokenManager.getToken().getAccessToken()));
        return objectMapper.readValue(post, new TypeReference<>() {
        });
    }

    /**
     * 2.3.2 获取单个停车场信息
     *
     * @param parkCode 停车场编号
     */
    @SneakyThrows
    public HkBaseHttpResp<HkParkInfoResp> parkInfo(String parkCode) {
        if (!StringUtils.hasLength(parkCode)) {
            throw new ApiException("停车场编号不能为空");
        }
        Map<String, String> headParams = new HashMap<>();
        headParams.put("access_token", HkAccessTokenManager.getToken().getAccessToken());
        String url = hkBaseTokenDTO.getBaseUrl() + MessageFormat.format(DEALER_PARK_CODE_URL, parkCode);
        try (HttpResponse execute = cn.hutool.http.HttpUtil.createPost(url).addHeaders(headParams).execute()) {
            String body = execute.body();
            return objectMapper.readValue(body, new TypeReference<>() {
            });
        }
    }

    /**
     * 2.3.3 获取剩余车位数
     *
     * @param parkCode 停车场编号
     */
    @SneakyThrows
    public HkBaseHttpResp<ParkRemainingSpaceResp> parkRemainingSpace(String parkCode) {
        if (!StringUtils.hasLength(parkCode)) {
            throw new ApiException("停车场编号不能为空");
        }
        Map<String, String> headParams = new HashMap<>();
        headParams.put("access_token", HkAccessTokenManager.getToken().getAccessToken());
        String url = hkBaseTokenDTO.getBaseUrl() + MessageFormat.format(DEALER_PARK_REMAINING_SPACE_URL, parkCode);
        try (HttpResponse execute = cn.hutool.http.HttpUtil.createPost(url).addHeaders(headParams).execute()) {
            String body = execute.body();
            return objectMapper.readValue(body, new TypeReference<>() {
            });
        }
    }

    /**
     * 2.3.4 获取出入口
     *
     * @param parkCodes 停车场编号列表
     */
    @SneakyThrows
    public HkBaseHttpResp<List<HkGateInfoResp>> gateInfos(List<String> parkCodes) {
        if (null == parkCodes || parkCodes.isEmpty()) {
            throw new ApiException("停车场编号列表不能为空");
        }
        String json = objectMapper.createObjectNode().putPOJO("parkCodes", parkCodes).toString();
        String post = httpUtil.sendHttpsPost(hkBaseTokenDTO.getBaseUrl() + DEALER_GATE_INFOS_URL, json, Map.of("access_token", HkAccessTokenManager.getToken().getAccessToken()));
        return objectMapper.readValue(post, new TypeReference<>() {
        });
    }

    /**
     * 2.3.5 获取车道
     *
     * @param gateCodes 出入口场编号列表
     */
    @SneakyThrows
    public HkBaseHttpResp<List<HkLaneInfoResp>> laneInfos(List<String> gateCodes) {
        if (null == gateCodes || gateCodes.isEmpty()) {
            throw new ApiException("出入口编号列表不能为空");
        }
        String json = objectMapper.createObjectNode().putPOJO("gateCodes", gateCodes).toString();
        String post = httpUtil.sendHttpsPost(hkBaseTokenDTO.getBaseUrl() + DEALER_LANE_INFOS_URL, json, Map.of("access_token", HkAccessTokenManager.getToken().getAccessToken()));
        return objectMapper.readValue(post, new TypeReference<>() {
        });
    }

    /**
     * 2.3.6 获取泊位
     *
     * @param parkCodes  停车场编号列表
     * @param berthState 泊位状态：0 空闲;1 占用;2未知
     */
    @SneakyThrows
    public HkBaseHttpResp<List<BerthInfoResp>> berthInfos(List<String> parkCodes, Integer berthState) {
        if (null == parkCodes || parkCodes.isEmpty()) {
            throw new ApiException("停车场编号列表不能为空");
        }
        ObjectNode objectNode = objectMapper.createObjectNode().putPOJO("parkCodes", parkCodes);
        if (null != berthState) {
            objectNode.put("berthState", berthState);
        }
        String post = httpUtil.sendHttpsPost(hkBaseTokenDTO.getBaseUrl() + DEALER_BERTH_INFOS_URL, objectNode.toString(), Map.of("access_token", HkAccessTokenManager.getToken().getAccessToken()));
        return objectMapper.readValue(post, new TypeReference<>() {
        });
    }
}